const fs = require('fs');

function shuffle(array) {
    let counter = array.length;

    // While there are elements in the array
    while (counter > 0) {
        // Pick a random index
        let index = Math.floor(Math.random() * counter);

        // Decrease counter by 1
        counter--;

        // And swap the last element with it
        let temp = array[counter];
        array[counter] = array[index];
        array[index] = temp;
    }

    return array;
}

class GameService {
    logs = [];
    chat = [];

		dice = [];
		canRollDice = 1;
		doublesRepeated = 0;

    newGame = () => {
        fs.writeFileSync(this.logFile, '');
        fs.writeFileSync(this.chatFile, '');
        return {
			turn: 1,
            dice: [3, 6],
            rollingDice: false,
			changedPlayer: false,
			someoneRollDice: false,
            started: false,
            players: [{
                id: 1,
				money: 20500,
                name: 'Bank',
				bankruptTurns: 0,
                token: 'dollar-sign',
                housing: {
                    hotels: 12,
                    houses: 32
                },
            }],
            deeds: {
                utilities: [
                    {
                        position: 12,
                        owner: "1",
                        title: "Electric Company",
                        type: "electricity",
                        description: "If one Utility is owned, rent is 4 times the amount shown on dice. If both Utilities are owned rent is 10 times amount shown on dice.",
                        price: "$150",
                        mortgaged: false
                    },
                    {
                        position: 28,
                        owner: "1",
                        type: "water",
                        title: "Water works",
                        description: "If one Utility is owned, rent is 4 times the amount shown on dice. If both Utilities are owned rent is 10 times amount shown on dice.",
                        price: "$150",
                        mortgaged: false
                    }
                ],
                trainStations: [
                    {
                        position: 5,
                        owner: "1",
                        title: "King's Cross Station",
                        rent: {
                            "Rent": '$25',
                            "If 2 Stations are Owned": "$50",
                            "If 3 Stations are Owned": "$100",
                            "If 4 Stations are Owned": "$200",
                        },
                        price: "$200",
                        mortgaged: false
                    },
                    {
                        position: 15,
                        owner: "1",
                        title: "Marylebone Station",
                        rent: {
                            "Rent": '$25',
                            "If 2 Stations are Owned": "$50",
                            "If 3 Stations are Owned": "$100",
                            "If 4 Stations are Owned": "$200",
                        },
                        price: "$200",
                        mortgaged: false
                    },
                    {
                        position: 25,
                        owner: "1",
                        title: "Fenchurch St. Station",
                        rent: {
                            "Rent": '$25',
                            "If 2 Stations are Owned": "$50",
                            "If 3 Stations are Owned": "$100",
                            "If 4 Stations are Owned": "$200",
                        },
                        price: "$200",
                        mortgaged: false
                    },
                    {
                        position: 35,
                        owner: "1",
                        title: "Liverpool St. Station",
                        rent: {
                            "Rent": '$25',
                            "If 2 Stations are Owned": "$50",
                            "If 3 Stations are Owned": "$100",
                            "If 4 Stations are Owned": "$200",
                        },
                        price: "$200",
                        mortgaged: false
                    },
                ],
                regular: [
                    {
                        position: 37,
                        owner: "1",
                        title: "Park Lane",
                        color: "#1a2596",
                        rent: {
                            "Rent": "$35",
                            "With colour set": "$70",
                            "With 1 House": "$175",
                            "With 2 House": "$500",
                            "With 3 House": "$1100",
                            "With 4 House": "$1300",
                            "With Hotel": "$1500",
                        },
                        cost: {
                            "House": "$200 each",
                            "Hotel": "$200 each"
                        },
                        houses: 0,
                        hotel: 0,
                        price: "$350",
                        mortgaged: false
                    },
                    {
                        position: 39,
                        owner: "1",
                        title: "MayFair",
                        color: "#1a2596",
                        rent: {
                            "Rent": "$50",
                            "With colour set": "$100",
                            "With 1 House": "$200",
                            "With 2 House": "$600",
                            "With 3 House": "$1400",
                            "With 4 House": "$1700",
                            "With Hotel": "$2000",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$200 each",
                            "Hotel": "$200 each"
                        },
                        price: "$400",
                        mortgaged: false
                    },
                    {
                        position: 31,
                        owner: "1",
                        title: "Regent Street",
                        color: "#008e04",
                        rent: {
                            "Rent": "$26",
                            "With colour set": "$52",
                            "With 1 House": "$130",
                            "With 2 House": "$390",
                            "With 3 House": "$900",
                            "With 4 House": "$1100",
                            "With Hotel": "$1275",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$200 each",
                            "Hotel": "$200 each"
                        },
                        price: "$300",
                        mortgaged: false
                    },
                    {
                        position: 34,
                        owner: "1",
                        title: "Bond Street",
                        color: "#008e04",
                        rent: {
                            "Rent": "$28",
                            "With colour set": "$56",
                            "With 1 House": "$150",
                            "With 2 House": "$450",
                            "With 3 House": "$1000",
                            "With 4 House": "$1200",
                            "With Hotel": "$1400",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$200 each",
                            "Hotel": "$200 each"
                        },
                        price: "$320",
                        mortgaged: false
                    },
                    {
                        position: 32,
                        owner: "1",
                        title: "Oxford Street",
                        color: "#008e04",
                        rent: {
                            "Rent": "$26",
                            "With colour set": "$52",
                            "With 1 House": "$130",
                            "With 2 House": "$390",
                            "With 3 House": "$900",
                            "With 4 House": "$1100",
                            "With Hotel": "$1275",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$200 each",
                            "Hotel": "$200 each"
                        },
                        price: "$300",
                        mortgaged: false
                    },
                    {
                        position: 26,
                        owner: "1",
                        title: "Leicester Square",
                        color: "#d6d105",
                        rent: {
                            "Rent": "$22",
                            "With colour set": "$44",
                            "With 1 House": "$110",
                            "With 2 House": "$330",
                            "With 3 House": "$800",
                            "With 4 House": "$975",
                            "With Hotel": "$1150",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$150 each",
                            "Hotel": "$150 each"
                        },
                        price: "$260",
                        mortgaged: false
                    },
                    {
                        position: 27,
                        owner: "1",
                        title: "Coventry Street",
                        color: "#d6d105",
                        rent: {
                            "Rent": "$22",
                            "With colour set": "$44",
                            "With 1 House": "$110",
                            "With 2 House": "$330",
                            "With 3 House": "$800",
                            "With 4 House": "$975",
                            "With Hotel": "$1150",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$150 each",
                            "Hotel": "$150 each"
                        },
                        price: "$260",
                        mortgaged: false
                    },
                    {
                        position: 29,
                        owner: "1",
                        title: "Picadilly",
                        color: "#d6d105",
                        rent: {
                            "Rent": "$24",
                            "With colour set": "$48",
                            "With 1 House": "$120",
                            "With 2 House": "$360",
                            "With 3 House": "$850",
                            "With 4 House": "$1025",
                            "With Hotel": "$1200",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$150 each",
                            "Hotel": "$150 each"
                        },
                        price: "$280",
                        mortgaged: false
                    },
                    {
                        position: 23,
                        owner: "1",
                        title: "Fleet Street",
                        color: "#9f0108",
                        rent: {
                            "Rent": "$18",
                            "With colour set": "$36",
                            "With 1 House": "$90",
                            "With 2 House": "$250",
                            "With 3 House": "$700",
                            "With 4 House": "$875",
                            "With Hotel": "$1050",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$150 each",
                            "Hotel": "$150 each"
                        },
                        price: "$220",
                        mortgaged: false
                    },
                    {
                        position: 21,
                        owner: "1",
                        title: "Strand",
                        color: "#9f0108",
                        rent: {
                            "Rent": "$18",
                            "With colour set": "$36",
                            "With 1 House": "$90",
                            "With 2 House": "$250",
                            "With 3 House": "$700",
                            "With 4 House": "$875",
                            "With Hotel": "$1050",
                        },
                        cost: {
                            "House": "$150 each",
                            "Hotel": "$150 each"
                        },
                        houses: 0,
                        hotel: 0,
                        price: "$220",
                        mortgaged: false
                    },
                    {
                        position: 24,
                        owner: "1",
                        title: "Trafalgar Square",
                        color: "#9f0108",
                        rent: {
                            "Rent": "$20",
                            "With colour set": "$40",
                            "With 1 House": "$100",
                            "With 2 House": "$300",
                            "With 3 House": "$750",
                            "With 4 House": "$925",
                            "With Hotel": "$1100",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$150 each",
                            "Hotel": "$150 each"
                        },
                        price: "$240",
                        mortgaged: false
                    },
                    {
                        position: 16,
                        title: "Bow Street",
                        color: "#d68000",
                        owner: "1",
                        rent: {
                            "Rent": "$14",
                            "With colour set": "$28",
                            "With 1 House": "$70",
                            "With 2 House": "$200",
                            "With 3 House": "$550",
                            "With 4 House": "$750",
                            "With Hotel": "$950",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$100 each",
                            "Hotel": "$100 each"
                        },
                        price: "$180",
                        mortgaged: false
                    },
                    {
                        position: 18,
                        title: "Marlborough Street",
                        color: "#d68000",
                        owner: "1",
                        rent: {
                            "Rent": "$14",
                            "With colour set": "$28",
                            "With 1 House": "$70",
                            "With 2 House": "$200",
                            "With 3 House": "$550",
                            "With 4 House": "$750",
                            "With Hotel": "$950",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$100 each",
                            "Hotel": "$100 each"
                        },
                        price: "$180",
                        mortgaged: false
                    },
                    {
                        position: 19,
                        title: "Vine Street",
                        color: "#d68000",
                        owner: "1",
                        rent: {
                            "Rent": "$16",
                            "With colour set": "$32",
                            "With 1 House": "$80",
                            "With 2 House": "$220",
                            "With 3 House": "$600",
                            "With 4 House": "$800",
                            "With Hotel": "$1000",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$100 each",
                            "Hotel": "$100 each"
                        },
                        price: "$200",
                        mortgaged: false
                    },
                    {
                        position: 13,
                        title: "WhiteHall",
                        color: "#930086",
                        owner: "1",
                        rent: {
                            "Rent": "$10",
                            "With colour set": "$20",
                            "With 1 House": "$50",
                            "With 2 House": "$150",
                            "With 3 House": "$450",
                            "With 4 House": "$625",
                            "With Hotel": "$750",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$100 each",
                            "Hotel": "$100 each"
                        },
                        price: "$140",
                        mortgaged: false
                    },
                    {
                        position: 11,
                        title: "Pall Mall",
                        color: "#930086",
                        owner: "1",
                        rent: {
                            "Rent": "$10",
                            "With colour set": "$20",
                            "With 1 House": "$50",
                            "With 2 House": "$150",
                            "With 3 House": "$450",
                            "With 4 House": "$625",
                            "With Hotel": "$750",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$100 each",
                            "Hotel": "$100 each"
                        },
                        price: "$140",
                        mortgaged: false
                    },
                    {
                        position: 14,
                        title: "Northumber land Avenue",
                        color: "#930086",
                        owner: "1",
                        rent: {
                            "Rent": "$12",
                            "With colour set": "$24",
                            "With 1 House": "$60",
                            "With 2 House": "$180",
                            "With 3 House": "$500",
                            "With 4 House": "$700",
                            "With Hotel": "$900",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$100 each",
                            "Hotel": "$100 each"
                        },
                        price: "$160",
                        mortgaged: false
                    },
                    {
                        position: 6,
                        title: "The Angel, Islington",
                        color: "#6ba9a5",
                        owner: "1",
                        rent: {
                            "Rent": "$6",
                            "With colour set": "$12",
                            "With 1 House": "$30",
                            "With 2 House": "$90",
                            "With 3 House": "$270",
                            "With 4 House": "$400",
                            "With Hotel": "$550",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$50 each",
                            "Hotel": "$50 each"
                        },
                        price: "$100",
                        mortgaged: false
                    },
                    {
                        position: 8,
                        title: "Euston Road",
                        color: "#6ba9a5",
                        owner: "1",
                        rent: {
                            "Rent": "$6",
                            "With colour set": "$12",
                            "With 1 House": "$30",
                            "With 2 House": "$90",
                            "With 3 House": "$270",
                            "With 4 House": "$400",
                            "With Hotel": "$550",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$50 each",
                            "Hotel": "$50 each"
                        },
                        price: "$100",
                        mortgaged: false
                    },
                    {
                        position: 9,
                        title: "Pentonville Road",
                        color: "#6ba9a5",
                        owner: "1",
                        rent: {
                            "Rent": "$8",
                            "With colour set": "$16",
                            "With 1 House": "$40",
                            "With 2 House": "$100",
                            "With 3 House": "$300",
                            "With 4 House": "$450",
                            "With Hotel": "$600",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$50 each",
                            "Hotel": "$50 each"
                        },
                        price: "$120",
                        mortgaged: false
                    },
                    {
                        position: 1,
                        title: "Old Kent Road",
                        color: "#614901",
                        owner: "1",
                        rent: {
                            "Rent": "$2",
                            "With colour set": "$4",
                            "With 1 House": "$10",
                            "With 2 House": "$30",
                            "With 3 House": "$90",
                            "With 4 House": "$160",
                            "With Hotel": "$250",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$50 each",
                            "Hotel": "$50 each"
                        },
                        price: "$60",
                        mortgaged: false
                    },
                    {
                        position: 3,
                        title: "WhiteChapel Road",
                        color: "#614901",
                        owner: "1",
                        rent: {
                            "Rent": "$4",
                            "With colour set": "$8",
                            "With 1 House": "$20",
                            "With 2 House": "$60",
                            "With 3 House": "$180",
                            "With 4 House": "$320",
                            "With Hotel": "$450",
                        },
                        houses: 0,
                        hotel: 0,
                        cost: {
                            "House": "$50 each",
                            "Hotel": "$50 each"
                        },
                        price: "$60",
                        mortgaged: false
                    },
                ],
            },
            cards: {
                chance: {
                    available: shuffle([
                        "Advance to go collect $200",
                        "You inherit $100",
                        "Go to Jail, Go directly to jail. Do not pass go. Do not collect $200",
                        "Holiday fund matures, collect $100",
                        "Income tax refund, collect $20",
                        "School fees. Pay $50",
                        "Hospital Fees. Pay $100",
                        "Collect $25 consultancy fee",
                        "Get out of jail free. This card may be kept until needed, traded or sold.",
                        "Bank error in your favour. Collect $200",
                        "It's your birthday collect $10 from each player",
                        "Life insurance matures. Collect $100",
                        "From sale of stock, you get $50",
                        "Doctor's fees. Pay $50"
                    ]),
                    used: [],
                },
                community: {
                    available: shuffle([
                        "Get out of jail free. This card may be kept until needed, traded or sold.",
                        "Go to Jail, Go directly to jail. Do not pass go. Do not collect $200",
                        "Advance to the next station. If UNOWNED, you may buy it from the bank. If OWNED, pay the owner twice the rent to which they are otherwise entitled",
                        "Advance to MayFair",
                        "Advance to the next station. If UNOWNED, you may buy it from the bank. If OWNED, pay the owner twice the rent to which they are otherwise entitled",
                        "You have been elected chairman of the board, pay each player $50",
                        "Advance to Trafalgar Square. If you pass go collect $200",
                        "Your building loan matures, collect $150",
                        "Advance to go, collect $200",
                        "Take atrop to king's cross station, if you pass go collect $200",
                        "Speeding fine, pay $15",
                        "Advance to the nearest utility, if UNOWNED, you may buy it from the bank. If OWNED, roll the dice and pay the owner 10 times your roll",
                        "Make general repairs on all you property: For each house pay $25, for each hotel pay $100",
                        "Go back 3 spaces",
                        "Advance to Pall Mall, if you pass go collect $200"
                    ]),
                    used: []

                }

            }
        }
    }
	getTurnFromId = (from) => {
		let i = 0;
		let turn = 0;
		while(i < this.game.players.length){
			if(this.game.players[i].id == from){
				turn = i;
			}
			i += 1;
		}
		return turn;
	}
	bankrupt = (playerId) => {

		this.game.deeds.regular.filter(s => s.owner == playerId).map(s => this.transferDeed(s.title, 'regular', 1, playerId));
		this.game.deeds.trainStations.filter(s => s.owner == playerId).map(s => this.transferDeed(s.title, 'trainStations', 1, playerId));
		this.game.deeds.utilities.filter(s => s.owner == playerId).map(s => this.transferDeed(s.title, 'utilities', 1, playerId));
		this.game.players.splice(this.game.players.indexOf(this.game.players[this.getTurnFromId(playerId)]), 1);

	}
	startTurn = (from) => {
		this.game.changedPlayer = false;
	}
	endTurn = (from) => {
		let name = this.game.players[this.game.turn].name;
		
		if(this.game.players[this.game.turn].id != 1){
			if(from == this.game.players[this.game.turn].id){
				if(this.canRollDice == 0){
					if(this.game.players[this.game.turn].money < -300){
						this.game.players[this.game.turn].bankruptTurns += 1;
						
						if(this.game.players[this.game.turn].bankruptTurns >= 3){
							this.bankrupt(this.game.players[this.game.turn].id);
						}
						this.sendLog(name + " will enter in bankruptcy in " + (3 - this.game.players[this.game.turn].bankruptTurns) + " turns.");
					}else{
						this.game.players[this.game.turn].bankruptTurns = 0;
					}

					this.game.turn += 1;
					this.game.turn = this.game.turn % this.game.players.length;

					if(this.game.players[this.game.turn].id == 1){
						this.game.turn += 1;
						this.game.turn = this.game.turn % this.game.players.length;
					}
					
					this.sendToWs();
					this.canRollDice = 1;

					this.game.changedPlayer = true;
					
				}else{
					if(this.reallyRollDice == 1){
						if(this.game.players[this.game.turn].money < -300){
							this.game.players[this.game.turn].bankruptTurns += 1;
							if(this.game.players[this.game.turn].bankruptTurns >= 3){
								this.bankrupt(this.game.players[this.game.turn].id);
							}
							this.sendLog(name + " will enter in bankruptcy in " + (3 - this.game.players[this.game.turn].bankruptTurns) + " turns.");
						}else{
							this.game.players[this.game.turn].bankruptTurns = 0;
						}

						this.game.turn += 1;
						this.game.turn = this.game.turn % this.game.players.length;
						if(this.game.players[this.game.turn].id == 1){
							this.game.turn += 1;
							this.game.turn = this.game.turn % this.game.players.length;
						}
						
						this.sendToWs();
						this.canRollDice = 1;
						this.reallyRollDice = 0;

						this.game.changedPlayer = true;
					}else{
						this.reallyRollDice = 1;
						this.sendLog(this.game.players[this.game.turn].name + " hasn't rolled the dice yet. Are you sure?");
					}
				}
			}else{
				this.sendLog(this.game.players[this.game.turn].name + " turn can't ended by others players.");
			}
		}else{
			this.game.turn += 1;
			this.game.turn = this.game.turn % this.game.players.length;
		}
		if(this.game.players[this.game.turn].name == "Bank"){
			this.sendLog(name + " won the game.");
		}else{
			this.sendLog(this.game.players[this.game.turn].name + " it's now your turn");
		}
	}
	cartesianToPosition = (x, y) => {

		if(x == 875 && y == 855){
			return 0;
		}else if(x == 905 && y == -2){
			return 10;
		}else if(x == 29 && y == 21){
			return 20;
		}else if(x == 29 && y == 879){
			return 30;
		}else if(x == 875){
			switch (y){
				case 767:return 1;break;
				case 686: return 2;break;
				case 606: return 3;break;
				case 528: return 4;break;
				case 446: return 5;break;
				case 368: return 6; break;
				case 290: return 7; break;
				case 209: return 8; break;
				case 129: return 9; break;
			}
		}else{
			if(y == 0){

				switch (x){
					case 767:return 11;break;
					case 686: return 12;break;
					case 606: return 13;break;
					case 528: return 14;break;
					case 446: return 15;break;
					case 368: return 16; break;
					case 290: return 17; break;
					case 209: return 18; break;
					case 129: return 19; break;
				}
			}else{
				if(x == 24){

					switch (y){
						case 767:return 29;break;
						case 686: return 28;break;
						case 606: return 27;break;
						case 528: return 26;break;
						case 446: return 25;break;
						case 368: return 24; break;
						case 290: return 23; break;
						case 209: return 22; break;
						case 129: return 21; break;
					}
				}else{
					if(y == 858){

						switch (x){
							case 767:return 39;break;
							case 686: return 38;break;
							case 606: return 37;break;
							case 528: return 36;break;
							case 446: return 35;break;
							case 368: return 34; break;
							case 290: return 33; break;
							case 209: return 32; break;
							case 129: return 31; break;
						}
					}
				}
			}
		}
		return 0;
    }
	positionToCartesian = ( position ) => {
		let cartesianList = [];
		position = position % 40;
		if(position == 0 || position == 40){
			cartesianList.push(875);
			cartesianList.push(855);
		}else if(position == 10){
			cartesianList.push(905);
			cartesianList.push(-2);
		}else if(position == 20){
			cartesianList.push(29);
			cartesianList.push(21);
		}else if(position == 30){
			cartesianList.push(29);
			cartesianList.push(879);

		}else if(position > 0 && position < 10){
			cartesianList.push(875);
			switch (position){
				case 1:cartesianList.push(767);break;
				case 2:cartesianList.push(686);break;
				case 3:cartesianList.push(606);break;
				case 4:cartesianList.push(528);break;
				case 5:cartesianList.push(446);break;
				case 6:cartesianList.push(368); break;
				case 7:cartesianList.push(290); break;
				case 8:cartesianList.push(209); break;
				case 9:cartesianList.push(129); break;
			}
		}else if(position < 20 && position >= 10){
			switch (position){
				case 11:cartesianList.push(767);break;
				case 12:cartesianList.push(686);break;
				case 13:cartesianList.push(606);break;
				case 14:cartesianList.push(528);break;
				case 15:cartesianList.push(446);break;
				case 16:cartesianList.push(368); break;
				case 17:cartesianList.push(290); break;
				case 18:cartesianList.push(209); break;
				case 19:cartesianList.push(129); break;
			}
			cartesianList.push(0);
		}else if(position < 30 && position >= 20){
			cartesianList.push(24);
			switch (position){
				case 29:cartesianList.push(767);break;
				case 28:cartesianList.push(686);break;
				case 27:cartesianList.push(606);break;
				case 26:cartesianList.push(528);break;
				case 25:cartesianList.push(446);break;
				case 24:cartesianList.push(368); break;
				case 23:cartesianList.push(290); break;
				case 22:cartesianList.push(209); break;
				case 21:cartesianList.push(129); break;
			}
		}else if(position < 40 && position >= 30){
			switch (position){
				case 39:cartesianList.push(767);break;
				case 38:cartesianList.push(686);break;
				case 37:cartesianList.push(606);break;
				case 36:cartesianList.push(528);break;
				case 35:cartesianList.push(446);break;
				case 34:cartesianList.push(368); break;
				case 33:cartesianList.push(290); break;
				case 32:cartesianList.push(209); break;
				case 31:cartesianList.push(129); break;
			}
			cartesianList.push(858);
		}
		return cartesianList;	
	}

    processCommand = (command, params, from) => {
        const player = this.getPlayerFromId(from);
        switch (command) {
            case 'rollDice':
                this.rollDice(0, this.randomInt(10) + 5, from);
                break;
            case 'newPlayer':
                this.addNewPlayer(params);
                break;
            case 'sendMoney':
                this.sendMoney(params.from, params.to, params.messages);
                break;
            case 'movePlayer':
                this.movePlayer(params.id, params.x, params.y);
                break;
            case 'moveFinished':
				this.moveToNearPosition(player.id, params.x, params.y);
                break;
            case 'sendDeed':
                this.transferDeed(params.street, params.type, params.to, from);
                break;
            case 'addHouse':
                this.addHouse(params.streetTitle, player);
                break;
            case 'removeHouse':
                this.removeHouse(params.streetTitle, player);
                break;
            case 'addHotel':
                this.addHotel(params.streetTitle, player);
                break;
            case 'removeHotel':
                this.removeHotel(params.streetTitle, player);
                break;
            case 'drawCard':
                this.drawCard(params.type, player);
                break;
            case 'loadGame':
                this.loadGame(params.game, player);
                break;
            case 'chat':
                this.addToChat(params.message, player);
                break;
			case 'mortgage':
				this.toggleMortgageDeed(params.title, params.type, player);break;
			case 'buyDeed':
				this.buyDeed(params.street, params.type, player);break;
			case 'endTurn':
				this.endTurn(from);break;
			case 'bankrupt':
				this.bankrupt(player.id);break;
			case 'startTurn':
				this.startTurn(from);break;
	
        }

        return {type: 'game', game: this.game};
    }
    toggleMortgageDeed = (title, type, from) => {
        const deed = this.game.deeds[type].find(s => s.title === title);

        let canMortgage = this.canMortgage(deed, from);
        console.log('Can mortgage?', canMortgage);
        if (canMortgage) {
			if(deed.mortgaged){
				const mortgageValue = Math.floor(Number(deed.price.substring(1))/ 2);
   				const tenPercent = Math.ceil(mortgageValue * 0.1);
				const mortgageBuyout = mortgageValue + tenPercent;

				if(from.money >= mortgageBuyout){
					from.money -= mortgageBuyout;
					deed.mortgaged = !deed.mortgaged;
          this.sendLog(from.name + " " + (deed.mortgaged ? "" : "un") + "mortgaged " + deed.title);
				}else{
					this.sendLog(from.name + " can't " + (deed.mortgaged ? "" : "un") + "mortgaged " + deed.title);
				}
			}else{
				const mortgageValue = Math.floor(Number(deed.price.substring(1))/ 2);

				from.money += mortgageValue;
				deed.mortgaged = !deed.mortgaged;
				this.sendLog(from.name + " " + (deed.mortgaged ? "" : "un") + "mortgaged " + deed.title);
			}

        } else {
            this.sendLog(from.name + " can't mortgage this property, either not the owner or other properties from the same color still have houses");
        }

    }

    canMortgage = (deed, user) => {
        console.log('can mortgage', deed, user);
        if (deed.owner !== user.id) {
            return false;
        }

        // it's a street, we need to check if there any houses left on the street of the same colors
        if (deed.color) {
            return this.game.deeds.regular.filter(d => d.color === deed.color)
                .every(d => d.houses === 0 && d.hotel === 0);
        } else {
            return true;
        }

    }


	buyDeed = (title, type, from) => {
        const owner = this.getPlayerFromId(this.game.deeds[type].find(s => s.title === title).owner);
		const player = this.getPlayerFromId(from.id);

        const deed = this.game.deeds[type].find(s => s.title === title);

		let position = this.cartesianToPosition(from.x, from.y);
        if (owner.name == "Bank"){
			if(position == deed.position) {
				var price = Number(deed.price.substring(1));
				if(player.money >= price){
				    deed.owner = from.id;
					player.money -= price;
					owner.money += price;
				    this.game.deeds[type].sort((s1, s2) => s2.position - s1.position);
				    this.game.deeds[type].sort((s1, s2) => s2.position - s1.position);

				    this.sendLog(from.name + " bought " + title );
				}else{
					this.sendLog(player.name + " doesn't have enough money to buy " + title);
				}
			}else{
				this.sendLog("You must be on " + title + " to buy it.");
			}

        } else {
            this.sendLog(title + " can't be bought from other's players");
        }
    }
    loadGame = (game, player) => {
        //removing keys that are not supposed to exist
        this.sendLog(player.name + ' is loading a saved game');
        Object.keys(game.game).forEach(k => {
            if (!this.game[k]) {
                delete game.game[k];
            }
        });

        this.game = {...this.newGame(), ...game.game};
        this.logs = game.logs || [];
        this.chat = game.chat || [];
        this.ws.broadcast(JSON.stringify({type: 'newGame', game: this.game}));
    }

    drawCard = (type, player) => {
        const cards = this.game.cards[type];

        if (cards.available.length === 0) {
            cards.available = shuffle(cards.used);
            cards.used = [];
            this.sendLog("No more " + type + " cards, shuffling the old ones");
        }

        const picked = cards.available.pop();
        cards.used.push(picked);
        this.sendLog(player.name + " draw  " + type + " card \"" + picked + "\"");

        this.ws.broadcast(JSON.stringify({type: 'cardDrawn', card: picked, cardType: type, player: player}));

    }

    canBuyHouse = (street, player) => {
        // get total of house of same color
        return this.game.deeds.regular.filter(s => street.color === s.color)
            .every(s => s.owner == player.id);

    }

    addHouse = (title, player) => {

        const street = this.game.deeds.regular.find(s => s.title === title);
        let bank = this.game.players.find(p => p.id == 1);
        const availableHouses = bank.housing.houses;

        if (!this.canBuyHouse(street, player)) {
            this.sendLog(player.name + " is not allowed to add houses to " + street.title);
            return;
        }

        if (player.id != street.owner) {
            this.sendLog(player.name + " is not the owner of " + street.title);
            return;
        }
        if (street.hotel === 1) {
            this.sendLog(street.title + " already has a hotel");
            return;
        }

        if (street.houses === 4) {
            this.sendLog(street.title + " already has 4 houses");
            return;
        }

        if (availableHouses > 0) {
			let cost = Number(street.cost["House"].substring(1, street.cost["House"].length - 5));
			if(player.money >= cost){
		        street.houses++;
				player.money -= cost;

		        bank.housing.houses--;
		        this.sendLog(player.name + " added one house to " + title);
		        this.sendLog("Bank balance: Houses: " + bank.housing.houses + ", Hotels: " + bank.housing.hotels);
			}else{
				this.sendLog(player.name + " doesn't have enough money to buy a new house");
			}
        } else {
            this.sendLog("No more houses in the bank");
        }

    }

    removeHouse = (title, player) => {

        const street = this.game.deeds.regular.find(s => s.title === title);
        let bank = this.game.players.find(p => p.id == 1);
        const availableHouses = bank.housing.houses;
        if (!this.canBuyHouse(street, player)) {
            this.sendLog(player.name + " is not allowed to add houses to " + street.title);
            return;
        }

        if (player.id != street.owner) {
            this.sendLog(player.name + " is not the owner of " + street.title);
            return;
        }

        if (street.houses === 0) {
            this.sendLog(street.title + " as no more houses to remove");
            return;
        }
		let	cost = Number(street.cost["House"].substring(1, street.cost["House"].length - 5));
        street.houses--;
		player.money += cost;
        bank.housing.houses++;
        this.sendLog(player.name + " removed one house from " + title);
        this.sendLog("Bank balance: Houses: " + bank.housing.houses + ", Hotels: " + bank.housing.hotels);

    }

    addHotel = (title, player) => {

        const street = this.game.deeds.regular.find(s => s.title === title);
        let bank = this.game.players.find(p => p.id == 1);
        const availableHotels = bank.housing.hotels;
        if (!this.canBuyHouse(street, player)) {
            this.sendLog(player.name + " is not allowed to add houses to " + street.title);
            return;
        }

        if (player.id != street.owner) {
            this.sendLog(player.name + " is not the owner of " + street.title);
            return;
        }

        if (street.houses < 4) {
            this.sendLog(street.title + " needs 4 houses to buy a hotel");
            return;
        }
		let	cost = Number(street.cost["Hotel"].substring(1, street.cost["Hotel"].length - 5));
        if (availableHotels > 0) {
			if(player.money > cost){
		        bank.housing.houses += street.houses;
		        bank.housing.hotels--;
		        street.hotel++;
		        street.houses = 0;
				player.money -= cost;
				bank.money += cost;
		        this.sendLog(player.name + " added one hotel to " + title);
		        this.sendLog("Bank balance: Houses: " + bank.housing.houses + ", Hotels: " + bank.housing.hotels);
			}else{
				this.sendLog(player.name + " doesn't have enough money to buy a new hotel");
			}
        } else {
            this.sendLog("No more hotels in the bank");
        }

    }

    removeHotel = (title, player) => {

        const street = this.game.deeds.regular.find(s => s.title === title);
        let bank = this.game.players.find(p => p.id == 1);
        const availableHotels = bank.housing.hotels;
        if (!this.canBuyHouse(street, player)) {
            this.sendLog(player.name + " is not allowed to add houses to " + street.title);
            return;
        }

        if (player.id != street.owner) {
            this.sendLog(player.name + " is not the owner of " + street.title);
            return;
        }

        if (street.hotel === 0) {
            this.sendLog(street.title + " as no more hotel to remove");
            return;
        }
		let	cost = Number(street.cost["Hotel"].substring(1, street.cost["Hotel"].length - 5));
        street.hotel--;
		player.money += cost;
		bank.money -= cost;
        bank.housing.hotels++;
        this.sendLog(player.name + " removed one hotel from " + title);
        this.sendLog("Bank balance: Houses: " + bank.housing.houses + ", Hotels: " + bank.housing.hotels);

    }

    transferDeed = (title, type, to, from) => {
        const owner = this.getPlayerFromId(this.game.deeds[type].find(s => s.title === title).owner);
        const toUser = this.getPlayerFromId(to);
        const deed = this.game.deeds[type].find(s => s.title === title);
        console.log('transfer deed:', deed);
        if (owner.id !== toUser.id) {

            // sending back to the bank, we give back the houses to the bank
            if (toUser.id === 1) {
                const houses = deed.houses;
                const hotel = deed.hotel;
                toUser.housing.hotels = toUser.housing.hotels + hotel;
                toUser.housing.houses = toUser.housing.houses + houses;
                deed.hotel = 0;
                deed.houses = 0;
                deed.mortgaged = false;
            }

            deed.owner = toUser.id;

            this.game.deeds[type].sort((s1, s2) => s2.position - s1.position);
            this.game.deeds[type].sort((s1, s2) => s2.position - s1.position);

            this.sendLog(this.getPlayerFromId(from).name + " transferred " + title + " from " + owner.name + " to " + toUser.name);

        } else {
            this.sendLog(title + " can't be sent to its current owner");
        }
    }
	getTypeOfPlace = (position) => {
		switch(position){
			case 0: return 'start';break;
			case 1: return 'regular';break;
			case 2: return 'community';break;
			case 3: return 'regular';break;
			case 4: return 'tax';break;
			case 5: return 'trainStations'; break;
			case 6: return 'regular'; break;
			case 7: return 'chance'; break;
			case 8: return 'regular'; break;
			case 9: return 'regular'; break;
			case 10: return 'visit'; break;
			
			case 11: return 'regular';break;
			case 12: return 'utilities'; break;
			case 13: return 'regular'; break;
			case 14: return 'regular'; break;
			case 15: return 'trainStations'; break;
			case 16: return 'regular'; break;
			case 17: return 'comunity'; break;
			case 18: return 'regular'; break;
			case 19: return 'regular'; break;
			case 20: return 'parking'; break;

			case 21: return 'regular';break;
			case 22: return 'chance'; break;
			case 23: return 'regular'; break;
			case 24: return 'regular'; break;
			case 25: return 'trainStations'; break;
			case 26: return 'regular'; break;
			case 27: return 'regular'; break;
			case 28: return 'utilities'; break;
			case 29: return 'regular'; break;
			case 30: return 'jail'; break;

			case 31: return 'regular';break;
			case 32: return 'regular'; break;
			case 33: return 'community'; break;
			case 34: return 'regular'; break;
			case 35: return 'trainStations'; break;
			case 36: return 'chance'; break;
			case 37: return 'regular'; break;
			case 38: return 'tax'; break;
			case 39: return 'regular'; break;
			case 40: return 'start'; break;
		}
	}
	moveToNearPosition = (playerId, x, y) => {
		var nearest_x, nearest_y;
		const max_position = 40;
		var i = 0;
		let cList = this.positionToCartesian(0);
		nearest_x = cList[0];
		nearest_y = cList[1];
		while(i < 40){
			let cartesianList = this.positionToCartesian(i);
			var test_x = cartesianList[0];
			var test_y = cartesianList[1];
			if((Math.abs(nearest_x - x) + Math.abs(nearest_y - y)) > (Math.abs(test_x - x) + Math.abs(test_y - y))){
				nearest_x = test_x;
				nearest_y = test_y;
			}
			i += 1;
		}
        const player = this.getPlayerFromId(playerId);
		player.x = nearest_x;
		player.y = nearest_y;
		
	}
    movePlayer = (playerId, x, y) => {
        const player = this.getPlayerFromId(playerId);
        player.x = x;
        player.y = y;
		let position = this.cartesianToPosition(x, y);
		if(position != 0){
			this.sendLog(player.name + " moved to position " + position);
		}
		this.checkPosition(position, playerId);
    }
	checkPosition = (position, playerId) => {
		let player = this.getPlayerFromId(playerId);
		let type = this.getTypeOfPlace(position);
		if(type == 'regular' || type == 'trainStations' || type == 'utilities')
			this.payIfNeccesary(position, playerId, type);
		if(type == 'jail'){
			let cartesianList = this.positionToCartesian(10);
			this.movePlayer(player.id, cartesianList[0], cartesianList[1]);
			player.money -= 50;
			this.sendLog(player.name + " had to pay a fine ($50) for entering prison");
			
		}
		if(type == 'tax'){
			player.money -= 200;
			this.sendLog(player.name + " pays $200 as taxes");
		}
	}
	getStationsFromPlayerId = (playerId) => {
		let stations = 0;
		let title = "King's Cross Station";
		stations += (this.game.deeds['trainStations'].find(s => s.title === title).owner == playerId);
		title = "Marylebone Station";
		stations += (this.game.deeds['trainStations'].find(s => s.title === title).owner == playerId);
		title = "Fenchurch St. Station";
		stations += (this.game.deeds['trainStations'].find(s => s.title === title).owner == playerId);
		title = "Liverpool St. Station";
		stations += (this.game.deeds['trainStations'].find(s => s.title === title).owner == playerId);
		return stations;
	}
	payIfNeccesary = (position, playerId, type) => {
		let player = this.getPlayerFromId(playerId);
		const owner = this.getPlayerFromId(this.game.deeds[type].find(s => s.position === position).owner);
		let rent = 0;
		if(owner.id != playerId && owner.name != "Bank"){
			let mortgage = this.game.deeds[type].find(s => s.position === position).mortgaged;
			if(!mortgage){
				if(type == 'trainStations'){
				
					let payStations = this.getStationsFromPlayerId(owner.id);
					let payStationsString;
					switch(payStations){
						case 1: payStationsString = "Rent";break;
						case 2: payStationsString = "If 2 Stations are Owned";break;
						case 3: payStationsString = "If 3 Stations are Owned";break;
						case 4: payStationsString = "If 4 Stations are Owned";break;
					}
					rent = Number(this.game.deeds[type].find(s => s.position === position).rent[payStationsString].substring(1));
					player.money -= rent;
					owner.money += rent;
				}
				if(type == 'regular'){
					let street = this.game.deeds[type].find(s => s.position === position);
					let payStations = this.canBuyHouse(street, owner);
					let payStationsString = "";
					if(!payStations){
						payStationsString = "Rent";
					}else{
						switch(street.houses){
							case 0: payStationsString = "With colour set";break;
							case 1: payStationsString = "With 1 House";break;
							case 2: payStationsString = "With 2 House";break;
							case 3: payStationsString = "With 3 House";break;
							case 4: payStationsString = "With 4 House";break;
						}
						if(street.hotel > 0) payStationsString = "With Hotel";
					}
					rent = Number(this.game.deeds[type].find(s => s.position === position).rent[payStationsString].substring(1));
					player.money -= rent;
					owner.money += rent;
				}
				if(type == 'utilities'){
					let electric = this.game.deeds['utilities'].find(s => s.position === 12);
					let water = this.game.deeds['utilities'].find(s => s.position === 28);
					var result = this.game.dice[0] + this.game.dice[1];
					if(electric.owner == owner.id && water.owner == owner.id){
						rent = result * 10;
						player.money -= rent;
						owner.money += rent;
					}else{
						
						if(electric.owner == owner.id){
							rent = result * 4;
							player.money -= rent;
							owner.money += rent;
						}else if(water.owner == owner.id){
							rent = result * 4;
							player.money -= rent;
							owner.money += rent;
						}
					}
				}
			}
			if(rent != 0){
				this.sendLog(player.name + " pay $" + rent + " to "+ owner.name);
			}
		}
	}
    addNewPlayer = (player) => {
        
        player.x = 888;
        player.y = 858;
				this.sendLog(player.money);
				player.money = 0;
        this.game.players.push(player);
				player.bankruptTurns = 0;
        this.sendMoney(1, player.id, 1500);

    }



    getPlayerFromId = (id) => {
        return this.game.players.find(p => p.id == id);
    }

	sendMoney = (from, to, messages) =>{
		var sum = Number(messages);
		const fromPlayer = this.getPlayerFromId(from);
        const toPlayer = this.getPlayerFromId(to);
		fromPlayer.money -= sum;
		toPlayer.money += sum;
        const logLine = fromPlayer.name + " sent $" + sum + " to " + toPlayer.name;
        this.sendLog(logLine);
        this.sendLog(fromPlayer.name + " new balance: $" + fromPlayer.money);
        this.sendLog(toPlayer.name + " new balance: $" + toPlayer.money);
    }

	transferMoney = (from, to, money) => {
		const fromPlayer = this.getPlayerFromId(from);
        const toPlayer = this.getPlayerFromId(to);

		fromPlayer.money -= money;
		toPlayer.money += money;
        const logLine = fromPlayer.name + " sent $" + money + " to " + toPlayer.name;
        this.sendLog(logLine);
        this.sendLog(fromPlayer.name + " new balance: $" + fromPlayer.money);
        this.sendLog(toPlayer.name + " new balance: $" + toPlayer.money);
    }

    randomInt = (max) => {
        return Math.floor(Math.random() * Math.floor(max));
    }

    sendToWs = () => {
        this.ws.broadcast(JSON.stringify({type: 'game', game: this.game}));
    }

    sendLog = (message) => {
        const date = new Date();
        message = "[" + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds() + "] " + message;
        this.logs.push(message);
        fs.appendFileSync(this.logFile, message + '\n', 'utf8');

        if (this.logs.length > 200) {
            this.logs.shift();
        }

        this.ws.broadcast(JSON.stringify({type: 'log', message: this.logs}));
    }

    addToChat = (message, player) => {
        const date = new Date();
        message = "[" + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds() + "] " + player.name + ": " + message;
        message.replace('<', '&lt;').replace('>', '&gt;');
        fs.appendFileSync(this.chatFile, message + '\n', 'utf8');
        this.chat.push(message);

        if (this.chat.length > 200) {
            this.chat.shift();
        }

        this.ws.broadcast(JSON.stringify({type: 'chat', message: this.chat}));
    }

    rollDice = (times, max, from) => {

		let player = this.getPlayerFromId(from);
        let bank = this.game.players.find(p => p.id == 1);
		if(this.game.players[this.game.turn].id == player.id){
			if(this.canRollDice == 1){
				this.sendToWs();

				this.game.dice[0] = this.randomInt(6) + 1;
	   			this.game.dice[1] = this.randomInt(6) + 1;

				this.sendLog(player.name + ' rolled ' + this.game.dice[0] + " and " + this.game.dice[1] + "!");

				let position = 0;
				position = this.cartesianToPosition(player.x, player.y);
				position += this.game.dice[0] + this.game.dice[1];

				if(position >= 40) {
					player.money += 200;
					bank.money -= 200;
				}
				let cartesianList = this.positionToCartesian(position);
				this.movePlayer(from, cartesianList[0], cartesianList[1]);

				if(this.game.dice[0] == this.game.dice[1]){
					if(this.doublesRepeated < 2){
						this.doublesRepeated += 1;
						this.canRollDice = 1;
					}else{
						this.canRollDice = 0;
						this.doublesRepeated = 0;
						let cartesianList = this.positionToCartesian(10);
						this.movePlayer(player.id, cartesianList[0], cartesianList[1]);
						this.sendLog(player.name + " moved too fast.");
						this.readableDice = 0;
					}
				}else{
					this.canRollDice = 0;
					this.doublesRepeated = 0;
				}
				
			}else{
				this.sendLog(player.name + " can't roll dice again.");
			}
	    }else{
			this.sendLog(player.name + " can't roll dice because it's other player turn.");
		}
    }

    logFile = './static/logs.txt';
    chatFile = './static/chat.txt';
    game = this.newGame();
    ws = undefined;
	
		
}
	
exports
    .gameService = new GameService();
